package com.gitee.qdbp.general.common.biz.reusable.service;

import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.jdbc.paging.Paging;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.model.consts.Keys;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeBean;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeCode;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeUpdate;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeWhere;
import com.gitee.qdbp.general.common.api.reusable.service.ISimpleTreeExecutor;
import com.gitee.qdbp.general.common.api.reusable.service.ISimpleTreeQueryer;
import com.gitee.qdbp.general.common.api.sequence.model.SimpleSequenceRule;
import com.gitee.qdbp.general.common.api.sequence.service.ISimpleSequenceGenerator;
import com.gitee.qdbp.general.common.biz.reusable.basic.SimpleTreeBasic;
import com.gitee.qdbp.general.common.error.TreeNodeErrorCode;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 基础树形数据业务处理类
 *
 * @author zhh
 * @version 170816
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class SimpleTreeExecutor implements ISimpleTreeExecutor {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(SimpleTreeExecutor.class);

    /**
     * 编号初始值<br>
     * 用于版本升级时兼容原先的编号机制<br>
     * 例如升级前最大的编号已达到40, 那么可以设置初始值为50
     */
    private int treeCodeInitValue = 1;
    @Autowired
    private SimpleTreeBasic simpleTreeBasic;
    @Autowired
    private ISimpleSequenceGenerator sequenceGenerator;

    @Override
    public void swapIndex(String scene, String oneCode, String twoCode, IAccount me) throws ServiceException {
        String msg = "Failed to swap SimpleTreeNodeIndex. ";
        // 判断SceneType不能为空
        if (VerifyTools.isBlank(scene)) {
            log.error(msg + "params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String tenantCode = me.getTenantCode();
        SimpleTreeBean one = findByCodeThrowOnNotExists(new SimpleTreeCode(scene, tenantCode, oneCode), msg);
        SimpleTreeBean two = findByCodeThrowOnNotExists(new SimpleTreeCode(scene, tenantCode, twoCode), msg);

        String parentCode = one.getParentCode();
        if (one.getSortIndex().equals(two.getSortIndex())) {
            int index = one.getSortIndex();
            { // 大于等于当前序号的全部加1
                SimpleTreeUpdate ud = new SimpleTreeUpdate();
                ud.setSortIndexAdd(1);
                SimpleTreeWhere where = ud.getWhere(true);
                where.setSceneType(scene);
                where.setParentCode(parentCode);
                where.setSortIndexMin(index);
                simpleTreeBasic.update(ud, false);
            }
            { // one再改成之前的序号
                SimpleTreeUpdate ud = new SimpleTreeUpdate();
                ud.setSortIndex(index);
                SimpleTreeWhere where = ud.getWhere(true);
                where.setSceneType(scene);
                where.setParentCode(parentCode);
                where.setNodeCode(one.getNodeCode());
                simpleTreeBasic.update(ud, false);
            }
        } else {
            { // one的序号改成two的序号
                SimpleTreeUpdate ud = new SimpleTreeUpdate();
                ud.setSortIndex(two.getSortIndex());
                SimpleTreeWhere where = ud.getWhere(true);
                where.setSceneType(scene);
                where.setParentCode(parentCode);
                where.setNodeCode(one.getNodeCode());
                simpleTreeBasic.update(ud, false);
            }
            { // two的序号改成one的序号
                SimpleTreeUpdate ud = new SimpleTreeUpdate();
                ud.setSortIndex(one.getSortIndex());
                SimpleTreeWhere where = ud.getWhere(true);
                where.setSceneType(scene);
                where.setParentCode(parentCode);
                where.setNodeCode(two.getNodeCode());
                where.setSortIndex(two.getSortIndex());
                simpleTreeBasic.update(ud, false);
            }
        }

    }

    @Override
    public void updateIndex(String scene, String code, int sortIndex, IAccount me) throws ServiceException {
        String msg = "Failed to update SimpleTreeNodeIndex. ";
        // 判断SceneType不能为空
        if (VerifyTools.isBlank(scene)) {
            log.error(msg + "params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String tenantCode = me.getTenantCode();
        SimpleTreeBean older = findByCodeThrowOnNotExists(new SimpleTreeCode(scene, tenantCode, code), msg);

        if (VerifyTools.equals(sortIndex, older.getSortIndex())) {
            return;
        }

        doUpdateIndex(scene, older, sortIndex, true, me);
    }

    private void doUpdateIndex(String scene, SimpleTreeBean older, int sortIndex, boolean moveSelf, IAccount me)
            throws ServiceException {

        if (sortIndex > older.getSortIndex()) { // 向后移
            // 先将中间的记录向前移
            // 如: 原先是3, 想移动到6, 则先将456向前移, 变成345, 再将原先的3变成6
            SimpleTreeUpdate ud = new SimpleTreeUpdate();
            ud.setSortIndexAdd(-1);
            SimpleTreeWhere where = ud.getWhere(true);
            where.setTenantCode(me.getTenantCode());
            where.setSceneType(scene);
            where.setSortIndexMin(older.getSortIndex() + 1);
            where.setSortIndexMax(sortIndex);
            where.setParentCode(older.getParentCode());
            simpleTreeBasic.update(ud, false);
        } else { // 向前移
            // 先将中间的记录向后移
            // 如: 原先是6, 想移动到3, 则先将345向后移, 变成456, 再将原先的6变成3
            SimpleTreeUpdate ud = new SimpleTreeUpdate();
            ud.setSortIndexAdd(+1);
            SimpleTreeWhere where = ud.getWhere(true);
            where.setTenantCode(me.getTenantCode());
            where.setSceneType(scene);
            where.setSortIndexMin(sortIndex);
            where.setSortIndexMax(older.getSortIndex() - 1);
            where.setParentCode(older.getParentCode());
            simpleTreeBasic.update(ud, false);
        }
        if (moveSelf) { // 再将自已移动到指定位置
            SimpleTreeUpdate ud = new SimpleTreeUpdate();
            ud.setSortIndex(sortIndex);
            SimpleTreeWhere where = ud.getWhere(true);
            where.setTenantCode(me.getTenantCode());
            where.setSceneType(scene);
            where.setId(older.getId());
            simpleTreeBasic.update(ud, true);
        }
    }

    @Override
    public String create(String scene, SimpleTreeBean model, IAccount me) throws ServiceException {
        String msg = "Failed to create SimpleTree. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        // 判断SceneType不能为空
        if (VerifyTools.isBlank(scene)) {
            log.error(msg + "params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        // 判断NodeText不能为空
        if (VerifyTools.isBlank(model.getNodeText())) {
            log.error(msg + "params is null: NodeText");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String parentCode = model.getParentCode();
        if (VerifyTools.isBlank(parentCode)) {
            model.setParentCode(parentCode = Keys.ROOT_CODE);
        }

        SimpleTreeCode parent = new SimpleTreeCode();
        parent.setTenantCode(me.getTenantCode());
        parent.setSceneType(scene);
        parent.setNodeCode(parentCode);

        int level = SimpleTreeQueryer.tools.level(parentCode);
        if (level > 0) { // 不是根节点
            findByCodeThrowOnNotExists(parent, msg);
        }

        if (VerifyTools.isBlank(model.getSortIndex())) { // 未指定, 添加到最后
            SimpleTreeWhere where = new SimpleTreeWhere();
            where.setTenantCode(model.getTenantCode());
            where.setSceneType(scene);
            where.setParentCode(parentCode);
            OrderPaging p = OrderPaging.of(new Paging(1, 1), "sortIndex desc"); // 按sortIndex降序取第1条
            PageList<SimpleTreeBean> temp = simpleTreeBasic.list(where, p);
            int sortIndex = 1;
            if (VerifyTools.isNotBlank(temp)) {
                SimpleTreeBean max = temp.get(0);
                sortIndex = Math.max(VerifyTools.nvl(max.getSortIndex(), 0) + 1, temp.getTotal());
            }
            model.setSortIndex(sortIndex);
        } else { // 将现在记录向后移, 为新记录腾出位置
            int sortIndex = model.getSortIndex();

            SimpleTreeUpdate ud = new SimpleTreeUpdate();
            ud.setSortIndexAdd(1);
            SimpleTreeWhere where = ud.getWhere(true);
            where.setTenantCode(model.getTenantCode());
            where.setSceneType(scene);
            where.setParentCode(parentCode);
            where.setSortIndexMin(sortIndex);
            simpleTreeBasic.update(ud, false);
        }

        // 生成节点编号: 上级节点编号加n位序号
        String nodeCode = createTreeNodeCode(parent);
        { // 插入记录
            model.setSceneType(scene);
            model.setNodeCode(nodeCode);
            model.setLevelIndex(level + 1);
            model.setId(null); // ID不允许指定
            model.setCreateTime(null); // 数据库默认值
            model.setCreatorId(me.getId());

            // 向gn_simple_tree表插入记录
            simpleTreeBasic.create(model);
        }

        return nodeCode;
    }

    /**
     * 生成节点编号: 上级节点编号加n位序号
     *
     * @param parent 上级节点
     * @return 节点编号
     * @throws ServiceException
     */
    private String createTreeNodeCode(SimpleTreeCode parent) throws ServiceException {
        VerifyTools.requireNotBlank(parent, "parent");
        VerifyTools.requireNotBlank(parent.getNodeCode(), "parent.code");

        String scene = parent.getSceneType();
        String tenantCode = parent.getTenantCode();
        String parentCode = parent.getNodeCode();

        int codeLength = ISimpleTreeQueryer.CATEGORY_CODE_LENGTH;
        SimpleSequenceRule rule = getTreeSequenceRule(parent);
        String nextCode = sequenceGenerator.use(rule).generate("TREE:" + scene, tenantCode, parentCode);
        int prefixLength = rule.getPrefix() == null ? 0 : rule.getPrefix().length();
        if (nextCode.length() - prefixLength > codeLength) {
            log.error("Tree code out of max limit. parentCode:[{}], codeLength:[{}]", parentCode, codeLength);
            throw new ServiceException(TreeNodeErrorCode.TREE_NODE_CODE_OUT_OF_MAX_LIMIT);
        }
        return nextCode;
    }

    protected SimpleSequenceRule getTreeSequenceRule(SimpleTreeCode bean) {
        String scene = bean.getSceneType();
        String parentCode = bean.getNodeCode();

        int codeLength = ISimpleTreeQueryer.CATEGORY_CODE_LENGTH;
        SimpleSequenceRule rule;
        if (parentCode.equals(Keys.ROOT_CODE)) {
            // 1000 + treeCodeInitValue
            rule = new SimpleSequenceRule((int) (Math.pow(10, codeLength - 1) + treeCodeInitValue));
        } else {
            rule = new SimpleSequenceRule(treeCodeInitValue, parentCode, codeLength);
        }
        rule.setName("TREE:" + scene);
        return rule;
    }

    /**
     * 检查节点是否存在, 不存在则报错
     *
     * @param model 节点信息
     * @throws ServiceException
     */
    private SimpleTreeBean findByCodeThrowOnNotExists(SimpleTreeCode model, String msg) throws ServiceException {

        SimpleTreeWhere where = new SimpleTreeWhere();
        where.setSceneType(model.getSceneType());
        where.setNodeCode(model.getNodeCode());
        where.setTenantCode(model.getTenantCode());

        SimpleTreeBean bean = simpleTreeBasic.find(where);

        if (bean == null) {
            log.warn(msg + "SimpleTree not found, nodeCode=" + model.getNodeCode());
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }
        return bean;
    }

    @Override
    public void update(String scene, SimpleTreeUpdate model, IAccount me) throws ServiceException {
        String msg = "Failed to update SimpleTree. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String id = model.getId();
        if (VerifyTools.isBlank(id) && model.getWhere() != null) {
            id = model.getWhere().getId();
        }
        String nodeCode = model.getNodeCode();
        if (VerifyTools.isBlank(nodeCode) && model.getWhere() != null) {
            nodeCode = model.getWhere().getNodeCode();
        }
        if (VerifyTools.isAllBlank(id, nodeCode)) {
            log.error(msg + "id or nodeCode is required.");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 原始记录检查
        SimpleTreeBean older;
        if (VerifyTools.isNotBlank(id)) {
            older = simpleTreeBasic.findById(id);
            if (older == null) {
                log.error(msg + "record is not found. id=" + id);
                throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
            }
        } else {
            older = simpleTreeBasic.findByNodeCode(nodeCode);
            if (older == null) {
                log.error(msg + "record is not found. code=" + nodeCode);
                throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
            }
        }

        SimpleTreeUpdate newer = createChangedModel(model, older);

        if (newer != null) {
            if (VerifyTools.isNotBlank(newer.getSortIndex())) { // 有修改排序号
                doUpdateIndex(scene, older, newer.getSortIndex(), false, me);
            }

            newer.getWhere(true).setSceneType(scene);
            // 更新gn_simple_tree表的记录
            simpleTreeBasic.update(newer, false);
        }
    }

    @Override
    public void deleteByCode(String scene, String code, IAccount me) throws ServiceException {
        String msg = "Failed to delete SimpleTree. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(code)) {
            log.error(msg + "params is null: code");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String tenantCode = me.getTenantCode();
        SimpleTreeBean older = findByCodeThrowOnNotExists(new SimpleTreeCode(scene, tenantCode, code), msg);
        { // SortIndex向前移
            int sortIndex = older.getSortIndex();

            SimpleTreeUpdate ud = new SimpleTreeUpdate();
            ud.setSortIndexAdd(-1);
            SimpleTreeWhere where = new SimpleTreeWhere();
            where.setTenantCode(tenantCode);
            where.setParentCode(older.getParentCode());
            where.setSortIndexMin(sortIndex + 1);
            simpleTreeBasic.update(ud, false);
        }

        { // 删除记录
            SimpleTreeWhere where = new SimpleTreeWhere();
            where.setSceneType(scene);
            where.setNodeCodeStarts(code);
            // 删除gn_simple_tree_info表的记录
            simpleTreeBasic.delete(where, false);
        }
    }

    @Override
    public void deleteByCodes(String scene, List<String> codes, IAccount me) throws ServiceException {
        for (String code : codes) {
            deleteByCode(scene, code, me);
        }
    }

    public int getTreeCodeInitValue() {
        return treeCodeInitValue;
    }

    public void setTreeCodeInitValue(int treeCodeInitValue) {
        this.treeCodeInitValue = treeCodeInitValue;
    }

    /**
     * 创建一个新的对象, 只包含改动过的字段
     *
     * @author zhh
     * @param model 目标对象(一般是参数传入的)
     * @param older 源对象(一般是从数据库查询得到的)
     * @return 只包含有更新的字段对象
     */
    private SimpleTreeUpdate createChangedModel(SimpleTreeUpdate model, SimpleTreeBean older) {
        SimpleTreeUpdate newer = new SimpleTreeUpdate();
        newer.setWhere(model.getWhere());

        boolean changed = false;
        newer.setId(model.getId()); // 主键
        newer.setNodeCode(model.getNodeCode()); // 节点编号

        // if (VerifyTools.isChanged(model.getTenantCode(), older.getTenantCode())) {
        //     changed = true;
        //     newer.setTenantCode(model.getTenantCode()); // 租户编号
        // }
        // if (VerifyTools.isChanged(model.getSceneType(), older.getSceneType())) {
        //     changed = true;
        //     newer.setSceneType(model.getSceneType()); // 使用场景
        // }
        if (VerifyTools.isChanged(model.getNodeText(), older.getNodeText())) {
            changed = true;
            newer.setNodeText(model.getNodeText()); // 节点名称
        }
        // if (VerifyTools.isChanged(model.getParentCode(), older.getParentCode())) {
        //     changed = true;
        //     newer.setParentCode(model.getParentCode()); // 上级编号
        // }
        if (VerifyTools.isChanged(model.getSortIndex(), older.getSortIndex())) {
            changed = true;
            newer.setSortIndex(model.getSortIndex()); // 排序号(越小越靠前)
        }
        // if (VerifyTools.isChanged(model.getLevelIndex(), older.getLevelIndex())) {
        //     changed = true;
        //     newer.setLevelIndex(model.getLevelIndex()); // 级数(从1开始)
        // }
        if (VerifyTools.isChanged(model.getLeaf(), older.getLeaf())) {
            changed = true;
            newer.setLeaf(model.getLeaf()); // 是否叶子节点
        }
        // if (VerifyTools.isChanged(model.getCreatorId(), older.getCreatorId())) {
        //     changed = true;
        //     newer.setCreatorId(model.getCreatorId()); // 创建人ID
        // }
        // if (VerifyTools.isChanged(model.getCreateTime(), older.getCreateTime())) {
        //     changed = true;
        //     newer.setCreateTime(model.getCreateTime()); // 创建时间
        // }
        if (VerifyTools.isChanged(model.getOptions(), older.getOptions())) {
            changed = true;
            newer.setOptions(model.getOptions()); // 选项
        }
        // if (VerifyTools.isChanged(model.getUsingState(), older.getUsingState())) {
        //     changed = true;
        //     newer.setUsingState(model.getUsingState()); // 启用状态(1.正常|2.未启用)
        // }
        // if (VerifyTools.isChanged(model.getDataState(), older.getDataState())) {
        //     changed = true;
        //     newer.setDataState(model.getDataState()); // 数据状态:0为正常|其他为删除
        // }
        // if (Boolean.TRUE.equals(model.isTenantCodeToNull())) {
        //     changed = true;
        //     newer.setTenantCodeToNull(true); // 租户编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isSceneTypeToNull())) {
        //     changed = true;
        //     newer.setSceneTypeToNull(true); // 使用场景更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isNodeNameToNull())) {
        //     changed = true;
        //     newer.setNodeNameToNull(true); // 节点名称更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isParentCodeToNull())) {
        //     changed = true;
        //     newer.setParentCodeToNull(true); // 上级编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isSortIndexToNull())) {
        //     changed = true;
        //     newer.setSortIndexToNull(true); // 排序号(越小越靠前)更新为空值
        // }
        // if (VerifyTools.isNotBlank(model.getSortIndexAdd()) && model.getSortIndexAdd() != 0) {
        //     changed = true;
        //     newer.setSortIndexAdd(model.getSortIndexAdd()); // 排序号(越小越靠前)的增加值
        // }
        // if (Boolean.TRUE.equals(model.isLevelIndexToNull())) {
        //     changed = true;
        //     newer.setLevelIndexToNull(true); // 级数(从1开始)更新为空值
        // }
        // if (VerifyTools.isNotBlank(model.getLevelIndexAdd()) && model.getLevelIndexAdd() != 0) {
        //     changed = true;
        //     newer.setLevelIndexAdd(model.getLevelIndexAdd()); // 级数(从1开始)的增加值
        // }
        // if (Boolean.TRUE.equals(model.isLeafToNull())) {
        //     changed = true;
        //     newer.setLeafToNull(true); // 是否叶子节点更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isCreatorIdToNull())) {
        //     changed = true;
        //     newer.setCreatorIdToNull(true); // 创建人ID更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isOptionsToNull())) {
        //     changed = true;
        //     newer.setOptionsToNull(true); // 选项更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isUsingStateToNull())) {
        //     changed = true;
        //     newer.setUsingStateToNull(true); // 启用状态(1.正常|2.未启用)更新为空值
        // }
        return changed ? newer : null;
    }

}
